package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.GameConstant;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.bag.BagConstant;
import com.motu.monstercity.server.game.commondata.bag.Box;
import com.motu.monstercity.server.game.commondata.bag.ItemId;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.userdata.UserCityInfo;
import com.motu.monstercity.server.game.userdata.UserInfo;
import io.vertx.core.json.JsonArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.tools.Tool;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class RewardManager {
    private static Logger logger = LoggerFactory.getLogger(RewardManager.class);

    // 添加奖励


    public static void addReward(UserInfo userInfo, RewardItem rewardItem, PBUserData.Builder pbUserData, Object... logParams) {
        addRewardPrompt(userInfo, rewardItem, pbUserData, true, logParams);// 默认飘窗显示提示信息
    }

    public static void addReward(UserInfo userInfo, int itemId, long itemNum, PBUserData.Builder pbUserData, Object... logParams) {
        RewardItem rewardItem = new RewardItem(itemId, itemNum);
        addRewardPrompt(userInfo, rewardItem, pbUserData, true, logParams);// 默认飘窗显示提示信息
    }

    // itemId;itemNum;itemId;itemNum;itemId;itemNum; 格式的字符串
    public static void addReward(UserInfo userInfo, String string, PBUserData.Builder pbUserData, Object... logParams) {
        List<RewardItem> list = CommonUtils.takeReawrdItemFromStr(string);
        addReward(userInfo, list, pbUserData, logParams);
    }

    public static void addReward(UserInfo userInfo, List<RewardItem> list, PBUserData.Builder pbUserData, Object... logParams) {
        List<RewardItem> rewardItemList = CommonUtils.mergeItemList(list);// 合办相同itemid的数量
        for (int i=0; i<rewardItemList.size(); i++) {
            RewardItem rewardItem = rewardItemList.get(i);
            addRewardPrompt(userInfo, rewardItem, pbUserData, true, logParams);// 默认飘窗显示提示信息
        }
    }

    // 扣除物品
    public static void subReward(UserInfo userInfo, RewardItem rewardItem, PBUserData.Builder pbUserData, Object... logParams) {
        subRewardPrompt(userInfo, rewardItem, pbUserData, logParams);// 默认飘窗显示提示信息
    }

    public static void subReward(UserInfo userInfo, int itemId, long itemNum, PBUserData.Builder pbUserData, Object... logParams) {
        RewardItem rewardItem = new RewardItem(itemId, itemNum);
        subRewardPrompt(userInfo, rewardItem, pbUserData, logParams);// 默认飘窗显示提示信息
    }

    // itemId;itemNum;itemId;itemNum;itemId;itemNum; 格式的字符串
    public static void subReward(UserInfo userInfo, String string, PBUserData.Builder pbUserData, Object... logParams) {
        List<RewardItem> list = CommonUtils.takeReawrdItemFromStr(string);
        subReward(userInfo, list, pbUserData, logParams);
    }

    public static void subReward(UserInfo userInfo, List<RewardItem> list, PBUserData.Builder pbUserData, Object... logParams) {
        List<RewardItem> rewardItemList = CommonUtils.mergeItemList(list);// 合办相同itemid的数量
        Map<Integer, Object> entityMap = list.stream().filter(item -> item.getEntity() != null).collect(Collectors.toMap(RewardItem::getItemId, RewardItem::getEntity));
        rewardItemList.forEach(item -> {
            if (entityMap.containsKey(item.getItemId())) {
                item.setEntity(entityMap.get(item.getItemId()));
            }
        });
        for (int i=0; i<rewardItemList.size(); i++) {
            RewardItem rewardItem = rewardItemList.get(i);
            subRewardPrompt(userInfo, rewardItem, pbUserData, logParams);// 默认飘窗显示提示信息
        }

    }


    /**
     * 某些道具不需要飘窗显示，如人口达到上限，或是超过上限提示实际获得的数量，宝箱自动打开
     * @param userInfo
     * @param rewardItem
     * @return
     */
    private static boolean checkIsPrompt(UserInfo userInfo, RewardItem rewardItem) {
        boolean isPrompt = true;
        long userId = userInfo.getId();
        int itemId = rewardItem.getItemId();
        long num = rewardItem.getItemNum();
        int itemType = GameConstant.getItemType(itemId);// itemid的类型

        if (itemId == ItemId.PERSON) {// 获得人口 人口不会消耗但不可超过城市人口总容量
            UserCityInfo userCityInfo = BuildManager.getUserCityInfo(userId);
            int max = BuildManager.getCityPeasonMax(userInfo) - userCityInfo.getPeasonNum();// 本次能增加的最大值
            if (max > 0) {
                if (max < num) {
                    rewardItem.setItemNum(max);// 实际获得的数量
                }
            } else {
                isPrompt = false;// 不获得人口
            }
        }

        if (itemType == GameConstant.REWARD_TYPE_BOX) {
            Box box = BagManager.getBox(itemId);
            if (box.getIsOpen() == 1) {
                isPrompt = false;// 宝箱配置了自动打开，则不显示在飘窗提升列表内
            }
        }

        return isPrompt;
    }



    /**
     * 获取奖励信息
     * @param userInfo 用户信息
     * @param rewardItem 获得的奖励
     * @param pbUserData
     * @param isPrompt 是否显示提示信息
     * @param logParams 日志参数
     */
    private static void addRewardPrompt(UserInfo userInfo, RewardItem rewardItem, PBUserData.Builder pbUserData, boolean isPrompt, Object... logParams) {
        int itemId = rewardItem.getItemId();
        long num = rewardItem.getItemNum();
        if (num < 1) {
            return;
        }

        if (isPrompt && checkIsPrompt(userInfo, rewardItem)) {// 客户端需要飘窗显示获得的奖励
            ProtoDataUtils.promptPBUserData(pbUserData, rewardItem);
        }
        int itemType = GameConstant.getItemType(itemId);// itemid的类型
        switch (itemType) {
            case GameConstant.REWARD_TYPE_PROP://  数值类型
                BagManager.addRewardProp(userInfo, rewardItem, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_BOX://
                Box box = BagManager.getBox(itemId);
                if (box == null) {
                    logger.error("box not found for boxId :{}", itemId);
                    break;
                }

                if (box.getIsOpen() == 1) {// 自动打开宝箱
                    if (box.getType() == BagConstant.BOX_REWARD_TYPE_0 || box.getType() == BagConstant.BOX_REWARD_TYPE_1) {
                        BagManager.autoOpenBoxReward(pbUserData, userInfo, box, (int)num, logParams);
                    } else if (box.getType() == BagConstant.BOX_REWARD_TYPE_4 || box.getType() == BagConstant.BOX_REWARD_TYPE_5) {
                        openDirectlyBox(userInfo, box, num, pbUserData, logParams);
                    }
                } else {  // 其他宝箱类用户数据也放在useritem
                    BagManager.addRewardProp(userInfo, rewardItem, pbUserData, logParams);
                }
                break;
            case GameConstant.REWARD_TYPE_PARTNER://  获得干员伙伴
                PartnerManager.addRewardPartner(userInfo, itemId, num, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_WEAPON://  获得武器
                PartnerManager.addRewardWeapon(userInfo, itemId, num, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_SUIT://  角色皮肤/服装
                SuitManager.addRewardSuit(userInfo, itemId, num, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_SECRETARY://  秘书
                SecretaryManager.addRewardSecretary(userInfo, itemId, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_BUILD://  建筑类
                BuildManager.addRewardBuild(userInfo, itemId, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_ROLE_DECORATE://  头像,头像框,称号,聊天气泡等装饰类
            case GameConstant.REWARD_TYPE_ROLE_DECORATE2://  头像,头像框,称号,聊天气泡等装饰类
                GameDataManager.addRewardDecorate(userInfo, itemId, (int)num, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_CHIP_MAIN://  碎片
                BagManager.addChipReward(userInfo, itemId, num, pbUserData, logParams);
                break;

        }
    }




    /**
     * 扣除奖励信息
     * @param userInfo 用户信息
     * @param rewardItem 扣除的奖励
     * @param pbUserData
     * @param logParams 日志参数
     */
    private static void subRewardPrompt(UserInfo userInfo, RewardItem rewardItem, PBUserData.Builder pbUserData, Object... logParams) {
        int itemId = rewardItem.getItemId();
        long num = rewardItem.getItemNum();
        if (num < 1) {
            return;
        }

        int itemType = GameConstant.getItemType(itemId);// itemid的类型
        switch (itemType) {
            case GameConstant.REWARD_TYPE_PROP:// 数值类
            case GameConstant.REWARD_TYPE_BOX:// 宝箱类也放在useritem
                BagManager.subRewardProp(userInfo, rewardItem, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_BUILD:// 建筑类装饰类建筑
                BuildManager.subRewardBuild(userInfo, itemId, pbUserData, logParams);
                break;
            case GameConstant.REWARD_TYPE_CHIP_MAIN:// 碎片
                BagManager.subChipReward(userInfo, itemId, num, pbUserData, logParams);
                break;
        }
    }

    /**
     * 道具字符串配置转map
     *
     * @param items 道具字符串配置（格式：道具ID;数量）
     * @return key道具ID，value数量
     */
    public static List<RewardItem> itemsToList(String items) {
        if (items == null || items.isEmpty()) {
            return new ArrayList<>();
        }
        String[] strAry = items.replace(" ", "").split(";");// 去除空格
        return itemsToList(strAry);
    }

    public static List<RewardItem> itemsToList(String[] strAry) {
        List<RewardItem> list = new ArrayList<>();
        ConcurrentHashMap<Integer, Long> itemMap = new ConcurrentHashMap<>();
        if (strAry.length < 2) {
            return list;
        }
        for (int i = 0; i < strAry.length / 2; i++) {
            int itemId = Integer.parseInt(strAry[i * 2]);
            long itemNum = Long.parseLong(strAry[i * 2 + 1]);
            if (itemId > 0 && itemNum > 0) {
                addItemMap(list,itemMap, itemId, itemNum);
            }
        }
        return list;
    }


    public static void addItemMap(List<RewardItem> itemList, ConcurrentHashMap<Integer, Long> itemMap,int itemId, long num) {
        long newNum = itemMap.getOrDefault(itemId, 0L) + num;
        itemMap.put(itemId, newNum);
        itemList.add(new RewardItem(itemId, newNum));
    }

    /**
     * 直接下发宝箱奖励
     */
    public static void openBox(UserInfo userInfo, List<RewardItem> boxList, PBUserData.Builder pbUserData, Object... logParams) {
        for (RewardItem boxItem : boxList) {
            int boxId = boxItem.getItemId();
            long num = boxItem.getItemNum();
            int itemType = GameConstant.getItemType(boxId);
            if (itemType != GameConstant.REWARD_TYPE_BOX) {
                addRewardPrompt(userInfo, boxItem, pbUserData, true, logParams);
                continue;
            }

            Box box = BagManager.getBox(boxId);
            if (box == null) {
                continue;
            }

            List<RewardItem> rewardItemList = new ArrayList<>();
            if (box.getType() == BagConstant.BOX_REWARD_TYPE_0 || box.getType() == BagConstant.BOX_REWARD_TYPE_1) {
                rewardItemList = BagManager.takeRewardFromBox(box, (int) num);
            }
            if (!rewardItemList.isEmpty()) {
                RewardManager.addReward(userInfo, rewardItemList, pbUserData, logParams);// 获得相应奖励
            }
        }
    }

    /**
     * @param addItemMap 被合并的mapa
     */
    public static void mergeItemMap(ConcurrentHashMap<Integer, Long> mainItemMap,
                                    ConcurrentHashMap<Integer, Long> addItemMap) {
        addItemMap.forEach((k, v) -> addItemMap(mainItemMap, k, v));
    }
    /**
     * @param addItemMap 被合并的mapa
     */
    public static void mergeItemMap(ConcurrentHashMap<Integer, Long> mainItemMap,
                                    List<RewardItem> addItemMap) {
        addItemMap.forEach(item -> addItemMap(mainItemMap, item.getItemId(), item.getItemNum()));
    }
    public static void addItemMap(ConcurrentHashMap<Integer, Long> itemMap, int itemId, long num) {
        long newNum = itemMap.getOrDefault(itemId, 0L) + num;
        itemMap.put(itemId, newNum);
    }

    // 直接下发宝箱奖励
    public static void openDirectlyBox(UserInfo userInfo, Box box, long totalNum, PBUserData.Builder pbUserData, Object... logParams) {
        if (box.getType() == BagConstant.BOX_REWARD_TYPE_4) { // 没有随机奖励，只有必得奖励，且包含宝箱类型5的宝箱
            int[] paramArr = CommonUtils.strToIntArray(box.getParam());
            List<RewardItem> allrewardList = new ArrayList<>();
            List<RewardItem> takeRewardList = CommonUtils.takeReawrdItemFromStr(box.getReward());
            CommonUtils.multipleItemList(takeRewardList, (int)totalNum);
            for (RewardItem rewardItem : takeRewardList) {
                int itemId = rewardItem.getItemId();
                long itemNum = rewardItem.getItemNum();
                int itemType = GameConstant.getItemType(itemId);// itemid的类型
                if (itemType == GameConstant.REWARD_TYPE_BOX) {
                    Box newBox = BagManager.getBox(itemId);
                    if (newBox != null && newBox.getType() == BagConstant.BOX_REWARD_TYPE_5 && newBox.getIsOpen() == 1) {
                        String param = "_" + String.valueOf(paramArr[1]);
                        String iapId = "";
                        String iapGiftInfoLogParams = "";
                        for (int i = 1; i < logParams.length; i++) {
                            if (i == logParams.length - 1) {  //是最后一个
                                iapGiftInfoLogParams += logParams[i];
                            } else {
                                iapGiftInfoLogParams += logParams[i] + ",";
                            }
                            if (i == 1){
                                iapId = String.valueOf(logParams[i]);
                            }
                        }
                        UnionManager.addUnionGiftBoxList(userInfo, itemId, itemNum, paramArr[0], iapId + param); // 给联盟的其他成员下发宝箱
                        autoOpenBox(userInfo, newBox, itemNum, pbUserData, LogType.UNION_GIFT_BOX_REWARD,iapGiftInfoLogParams); // 自己的直接打开
                        continue;
                    }
                }
                allrewardList.add(rewardItem);
            }
            for (RewardItem rewardItem : allrewardList) {
                BagManager.addRewardProp(userInfo, rewardItem, pbUserData, logParams);
            }
        } else if (box.getType() == BagConstant.BOX_REWARD_TYPE_5) {
            autoOpenBox(userInfo, box, totalNum, pbUserData, logParams);
        }

    }

    /***
     * 自动打开宝箱
     * @param userInfo
     * @param box
     * @param totalNum
     * @param pbUserData
     * @param logParams
     */
    public static void autoOpenBox(UserInfo userInfo, Box box, long totalNum, PBUserData.Builder pbUserData, Object... logParams) {
        List<RewardItem> rewardItemList = BagManager.takeBoxRandomRewardAndMustReward(box, (int)totalNum);
        for (RewardItem rewardItem : rewardItemList) {
            BagManager.addRewardProp(userInfo, rewardItem, pbUserData, logParams);
            if (rewardItem.getItemId() != ItemId.TYPE_UNION_BOX_ITEM){
                ProtoDataUtils.promptPBUserData(pbUserData, rewardItem);
            }
        }
    }

    /**
     * 奖励map转奖励列表
     */
    public static List<RewardItem> itemMap2RewardList(ConcurrentHashMap<Integer, Long> itemMap) {
        List<RewardItem> list = new ArrayList<>();
        itemMap.forEach((k, v) -> list.add(new RewardItem(k, v)));
        return list;
    }

}
